package com.nathan.crm.service;

import com.nathan.base.BaseService;
import com.nathan.crm.dao.UserMapper;
import com.nathan.crm.dao.UserRoleMapper;
import com.nathan.crm.model.UserModel;
import com.nathan.crm.utils.AssertUtil;
import com.nathan.crm.utils.Md5Util;
import com.nathan.crm.utils.PhoneUtil;
import com.nathan.crm.utils.UserIDBase64;
import com.nathan.crm.vo.User;
import com.nathan.crm.vo.UserRole;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Service
public class UserService extends BaseService<User,Integer> {
    @Resource
    private UserMapper userMapper;
    @Resource
    private UserRoleMapper userRoleMapper;

    /**
     * 用户登录
     * @param username
     * @param userPwd
     * @return
     */
    public UserModel userLogin(String username,String userPwd){
        // 1、参数判断，判断用户名和密码是否为空
        checkLoginParams(username,userPwd);

        // 2、调用dao层，根据用户名查询用户，返回用户对象
        User user = userMapper.queryByUsername(username);

        // 3、判断用户是否为空
        AssertUtil.isTrue(user == null,"用户姓名不存在！");

        // 4、判断用户密码是否正确
        AssertUtil.isTrue(!Md5Util.encode(userPwd).equals(user.getUserPwd()),"用户密码错误！");

        // 5、返回用户构建对象
        return buildUserInfo(user);
    }

    /**
     * 修改用户密码
     * @param userId
     * @param oldPwd
     * @param newPwd
     * @param repeatPwd
     */
    @Transactional
    public void updateUserPassword(Integer userId,String oldPwd,String newPwd,String repeatPwd){
        // 通过用户ID查询用户记录，返回用户对象
        User user = userMapper.selectByPrimaryKey(userId);

        // 判断用户是否为空
        AssertUtil.isTrue(null == user,"待更新记录不存在！");

        // 密码校验
        checkPasswordParams(user,oldPwd,newPwd,repeatPwd);

        // 设置用户的新密码
        user.setUserPwd(Md5Util.encode(newPwd));

        // 执行更新操作，判断受影响的行数
        Integer i = userMapper.updateByPrimaryKeySelective(user);
        AssertUtil.isTrue(i < 1,"密码更新失败！");
    }

    /**
     * 查询所有角色为销售的用户
     * @return
     */
    public List<Map<String,Object>> selectAllSales(){
        return userMapper.selectAllSales();
    }

    /**
     * 密码校验
     * @param user
     * @param oldPwd
     * @param newPwd
     * @param repeatPwd
     */
    private void checkPasswordParams(User user,String oldPwd, String newPwd, String repeatPwd) {
        //判断原始密码是否为空
        AssertUtil.isTrue(StringUtils.isBlank(oldPwd),"原始密码不能为空！");
        //判断原始密码是否正确(查询的用户对象中的用户密码是否原始密码一致)
        AssertUtil.isTrue(!user.getUserPwd().equals(Md5Util.encode(oldPwd)),"原始密码输入错误！");
        //判断新密码是否为空
        AssertUtil.isTrue(StringUtils.isBlank(newPwd),"新密码不能为空！");
        //判断新密码是否与原始密码一致(不允许新密码与原始密码一致)
        AssertUtil.isTrue(newPwd.equals(oldPwd),"新密码不能和原始密码相同！");
        //判断确认密码是否为空
        AssertUtil.isTrue(StringUtils.isBlank(repeatPwd),"确认密码不能为空！");
        //判断确认密码是否与新密码一致
        AssertUtil.isTrue(!newPwd.equals(repeatPwd),"两次密码输入不一致");

    }

    /**
     * 用户构建对象
     * @param user
     * @return
     */
    private UserModel buildUserInfo(User user){
        UserModel userModel = new UserModel();
        //设置加密后的userId
        userModel.setUserIdStr(UserIDBase64.encoderUserID(user.getId()));
        userModel.setUserName(user.getUserName());
        userModel.setTrueName(user.getTrueName());

        return userModel;
    }

    /**
     * 参数判断，判断用户名和密码是否为空
     * @param username
     * @param userPwd
     */
    private void checkLoginParams(String username, String userPwd) {
        AssertUtil.isTrue(StringUtils.isBlank(username),"用户名不能为空！");
        AssertUtil.isTrue(StringUtils.isBlank(userPwd),"用户密码不能为空!");
    }

    /**
     *  添加用户
     *      1、参数校验
     *          userName    非空，惟一
     *          email       非空
     *          phone       非空
     *      2、设置参数默认值
     *          is_valid    1
     *          create_date     当前系统时间
     *          默认密码        123456-->md5加密
     *      3、执行添加操作
     * @param user
     */
    @Transactional
    public void addUser(User user){
        /* 1、参数校验 */
        checkUserParams(user.getUserName(),user.getEmail(),user.getPhone(),user.getId());

        /* 2、设置参数默认值 */
        user.setIsValid(1);
        user.setCreateDate(new Date());
        user.setUpdateDate(new Date());
        user.setUserPwd(Md5Util.encode("123456"));

        /* 3、执行添加操作 */
        AssertUtil.isTrue(userMapper.insertHasKey(user) < 1,"添加用户失败！");

        /* 用户角色关联 */
        relationUserRole(user.getId(),user.getRoleIds());
    }

    /**
     * 用户角色关联
     *      添加操作
     *          原始角色不存在
     *              1、不添加新的角色记录     不操作用户角色表
     *              2、添加新的角色记录      给指定用户绑定相关的角色记录
     *      更新操作
     *          原始角色不存在
     *              1、不添加新的角色记录     不操作用户角色表
     *              2、添加新的角色记录      给指定用户绑定相关的角色记录
     *              原始角色存在
     *                  1、添加新的角色记录      断已有的角色记录不添加,添加没有的角色记录
     *                  2、清空所有的角色记录     删除用户绑定角色记录
     *                  3、移除部分角色记录       删除不存在的角色记录，存在的角色记录保留
     *                  4、移除部分角色，添加新的角色     删除不存在的角色记录，存在的角色记录保留，添加新的角色
     *
     *      如何进行角色分配???
     *          判断用户对应的角色记录存在，将用户原有的角色记录删除,添加新的角色记录
     *      删除操作
     *          删除指定用户绑定的角色记剥
     *
     * @param userId    用户id
     * @param roleIds   角色id
     */
    private void relationUserRole(Integer userId, String roleIds) {
        // 通过用户ID查询角色记录
        Integer count = userRoleMapper.countUserRole(userId);
        // 判断角色记录是否存在
        if (count > 0){
            // 角色记录存在，则删除该用户对应的角色记录
            AssertUtil.isTrue(userRoleMapper.deleteUserRole(userId) != count,"角色分配失败！");
        }
        // 判断角色ID是否存在
        if (StringUtils.isNotBlank(roleIds)){
            // 存在，添加该用户对应的角色记录
            // 创建一个UserRole的集合对象，存储所有要存储的角色记录
            List<UserRole> list = new ArrayList<>();
            // 将角色字符串转为数组
            String[] roleIdsArray = roleIds.split(",");
            // 遍历字符串,创建对应的用户角色关联对象
            for (String roleId : roleIdsArray) {
                UserRole userRole = new UserRole();
                userRole.setUserId(userId);
                userRole.setRoleId(Integer.parseInt(roleId));

                list.add(userRole);
            }

            // 批量添加用户角色关联对象
            AssertUtil.isTrue(userRoleMapper.insertBatch(list) != list.size(),"角色分配失败！");
        }
    }

    /**
     * 更新用户
     *      1、参数校验
     *          判断用户ID是否为空,且数据存在
     *          用户名userName 非空，唯一性
     *          邮箱email     非空
     *          手机号phone    非空，格式正确
     *      2、执行更新操作，判断受影响的行数
     * @param user
     */
    @Transactional
    public void updateUser(User user){
        /* 1、参数校验 */
        // 判断用户ID是否为空,且数据存在
        AssertUtil.isTrue(null == user.getId(),"待更新用户不存在！");
        // 参数校验
        checkUserParams(user.getUserName(),user.getEmail(),user.getPhone(),user.getId());

        /* 2、执行更新操作 */
        AssertUtil.isTrue(userMapper.updateByPrimaryKeySelective(user) != 1,"用户更新失败！");

        /* 用户角色关联 */
        relationUserRole(user.getId(),user.getRoleIds());
    }

    /**
     * 参数校验
     * @param userName
     * @param email
     * @param phone
     */
    private void checkUserParams(String userName, String email, String phone,Integer userId) {
        // userName    非空，惟一
        AssertUtil.isTrue(StringUtils.isBlank(userName),"用户名不能为空！");
        // 根据用户名查询数据
        User user = userMapper.queryByUsername(userName);
        // 如果是添加用户，只需要判断该用户存不存在即可
        // 如果是更新操作，如果用户存在，还需要判断更新的用户id和查询到的用户id是否一致，不一致表示用户名被占用
        AssertUtil.isTrue(null != user && !(user.getId().equals(userId)),"用户名已存在，请重新输入！");
        // email       非空
        AssertUtil.isTrue(StringUtils.isBlank(email),"邮箱不能为空");
        // phone       非空
        AssertUtil.isTrue(StringUtils.isBlank(phone),"电话号码不能为空！");
        // 电话号码格式校验
        AssertUtil.isTrue(!PhoneUtil.isMobile(phone),"电话号码格式错误，请重新输入！");
    }

    /**
     * 删除一条或多条用户
     * @param ids
     */
    @Transactional
    public void deleteUser(Integer[] ids) {
        // 参数判断
        AssertUtil.isTrue(ids == null || ids.length == 0,"请选择要删除的记录！");

        // 执行删除操作
        userMapper.deleteBatch(ids);

        // 跟具用户id删除用户角色关联信息
        for (Integer id : ids){
            // 判断用户id是否有对应的角色
            Integer count = userRoleMapper.countUserRole(id);
            if (count > 0){
                // 有值，删除
                AssertUtil.isTrue(userRoleMapper.deleteUserRole(id) != count,"用户角色删除失败！");
            }
        }
    }

    /**
     * 查询所有角色为客户经理的用户
     * @return
     */
    public List<Map<String, Object>> queryAllCustomerManager() {
        return userMapper.queryAllCustomerManager();
    }
}
